package imp

import (
	sqlc "bgs/db/sqlc"
	brandGrpc "bgs/grpc/gen/service/brand"
	"bgs/grpc/gen/shared/message"
	"bgs/grpc/imp/constants"
	"bgs/grpc/imp/enums"
	"bgs/grpc/imp/shared"
	brandService "bgs/service/brand"
	"bgs/service/model"
	productService "bgs/service/product"
	"bgs/util"
	"context"
	"database/sql"
	"encoding/json"
	"fmt"
	"strconv"
	"time"
)

/****************************************************************************************/
/*                               brand entity of helper                                 */
/****************************************************************************************/

func transformBrandEntityToPb(o sqlc.Brand) *brandGrpc.BrandEntity {
	return &brandGrpc.BrandEntity{
		Id:         o.ID,
		Origin:     o.Origin,
		Name:       o.Name,
		Intro:      o.Intro.String,
		Pic:        o.Pic.String,
		HomepageBg: o.HomepageBg.String,
		Tel:        o.Tel.String,
		Opened:     sqlc.GoTimeToPBTimestamp(o.Opened),
		RemotePk:   o.RemotePk,
	}
}

func transformBilinBrandEntityToPb(o model.BilinBrand) *brandGrpc.BilinBrandEntity {
	return &brandGrpc.BilinBrandEntity{
		RemotePkOfBrand:    o.RemotePkOfBrand,
		RemotePkOfEmployee: o.RemotePkOfEmployee,
		Name:               o.Name,
		Logo:               o.Logo,
		Desc:               o.Desc,
	}
}

func mapBilinBrandEntityToPb(list []model.BilinBrand, f func(model.BilinBrand) *brandGrpc.BilinBrandEntity) []*brandGrpc.BilinBrandEntity {
	r := make([]*brandGrpc.BilinBrandEntity, len(list))
	for i, item := range list {
		r[i] = f(item)
	}
	return r
}

/****************************************************************************************/
/*                               brand entity of cmd                                    */
/****************************************************************************************/

// OldOpenBrand 开通品牌(旧:和bilin后台系统分开)
func (s *BrandAPIService) OldOpenBrand(ctx context.Context, req *brandGrpc.OpenBrandRequest) (res *brandGrpc.OpenBrandResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brandImp->OpenBrand:%v", req)

	res = &brandGrpc.OpenBrandResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}

	var brand sqlc.Brand
	// 多个数据操作,使用事务
	err = s.dao.NewTxRunner().SqlcExecTx(ctx, func(q *sqlc.Queries) (err error) {

		remotePk := req.RemotePk
		txTime := time.Now()
		syncAction := req.SyncAction

		// 1 创建品牌
		brand, err = q.CreateBrand(ctx, sqlc.CreateBrandParams{
			Origin:   req.Origin,
			Name:     req.Name,
			Intro:    sqlc.NSFromString(req.Intro),
			Pic:      sqlc.NSFromString(req.Pic),
			RemotePk: remotePk,
		})
		if err != nil {
			return err
		}
		slog.Info("1 创建品牌 ok")

		user, err := q.GetUser(ctx, req.UserId)
		if err != nil {
			return err
		}
		if !user.Mobile.Valid {
			return fmt.Errorf("user has not bind mobile: %d", user.ID)
		}

		// 2 创建品牌管理员
		_, err = q.UpsertBrandAdminOld(ctx, sqlc.UpsertBrandAdminOldParams{
			UserID:    user.ID,
			BrandID:   brand.ID,
			AliasName: user.Mobile.String,
			Became:    txTime,
		})
		if err != nil {
			return err
		}
		slog.Info("2 创建品牌管理员 ok")

		// 3 设置品牌的所有者
		_, err = q.UpsertBrandExt(ctx, sqlc.UpsertBrandExtParams{
			BrandID:   brand.ID,
			OwnUserID: user.ID,
		})
		if err != nil {
			return err
		}
		slog.Info("3 设置品牌的所有者 ok")

		//4 设置同步
		localObj, localPkName, localFields := constants.SyncLocalObjBrand, constants.SyncLocalPkNameBrand, constants.SyncLocalFieldsBrand
		remoteObj, remotePkName, remoteFields := constants.SyncRemoteObjBrand, constants.SyncRemotePkNameBrand, constants.SyncRemoteFieldsBrand

		sync, err := q.UpsertSync(ctx, sqlc.UpsertSyncParams{
			LocalObj:         localObj,
			LocalPkName:      localPkName,
			LocalFields:      localFields,
			RemoteObj:        remoteObj,
			RemotePkName:     remotePkName,
			RemoteFields:     remoteFields,
			LatestSynced:     txTime,
			LatestSyncAction: syncAction,
		})
		if err != nil {
			return err
		}
		slog.Info("4 品牌同步 ok")

		localPK := strconv.FormatInt(brand.ID, 10)
		// 5 同步映射
		syncMapping, err := q.UpsertSyncMapping(ctx, sqlc.UpsertSyncMappingParams{
			SyncID:    sync.ID,
			LocalObj:  localObj,
			LocalPk:   localPK,
			RemoteObj: remoteObj,
			RemotePk:  strconv.FormatInt(remotePk, 10),
		})
		if err != nil {
			return err
		}
		slog.Info("5 品牌同步映射 ok")

		// 6 同步日志
		syncData, err := json.Marshal(struct {
			ID   int64  `json:"id"`
			Name string `json:"name"`
		}{
			ID:   brand.ID,
			Name: brand.Name,
		})
		if err != nil {
			return err
		}

		maxVer, err := q.GetSyncLogMaxVer(ctx, sqlc.NInt64FromInt64(syncMapping.ID))
		if err != nil {
			return err
		}
		_, err = q.CreateSyncLog(ctx, sqlc.CreateSyncLogParams{
			SyncID:        sync.ID,
			SyncMappingID: sqlc.NInt64FromInt64(syncMapping.ID),
			LocalObj:      localObj,
			LocalPk:       localPK,
			RemoteObj:     remoteObj,
			RemotePk:      strconv.FormatInt(remotePk, 10),
			Synced:        txTime,
			Action:        syncAction,
			Data:          syncData,
			SyncStatus:    string(enums.SyncStatusDone),
			Ver:           int64(maxVer + 1),
		})
		if err != nil {
			return err
		}
		slog.Info("6 品牌同步日志 ok")
		return
	})
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.Brand = transformBrandEntityToPb(brand)
	return
}

// OpenNew 开通新品牌
func (s *BrandAPIService) OpenNew(ctx context.Context, req *brandGrpc.OpenNewRequest) (res *brandGrpc.OpenNewResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brandImp->OpenNew:%v", req)

	res = &brandGrpc.OpenNewResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}

	var brand sqlc.Brand
	err = s.dao.NewTxRunner().SqlcExecTx(ctx, func(q *sqlc.Queries) (err error) {

		userID := req.UserId
		remotePkOfBrand := req.RemotePkOfBrand
		user, err := q.GetUser(ctx, userID)
		if err != nil {
			return
		}
		if !user.Mobile.Valid {
			err = fmt.Errorf("user mobile is invalid")
			return
		}
		userAccountToken, err := s.userService.FetchUserAccountTokenSafely(ctx, q, &user)
		if err != nil {
			return
		}
		slog.Infof("1、获取用户的accountToken ok")

		if remotePkOfBrand > 0 {
			existed, sqlErr := q.CheckExistBrandByRemotePk(ctx, remotePkOfBrand)
			if sqlErr != nil {
				err = sqlErr
				return
			}

			if existed {
				err = fmt.Errorf("该品牌已经开通")
				return
			}
		}

		brand, err = s.brandService.OpenNew(ctx, q, &brandService.OpenNewParam{
			UserID:             userID,
			UserNickName:       util.StringIfThenElse(user.NickName.Valid, user.NickName.String, user.Mobile.String),
			UserAccountToken:   userAccountToken,
			Name:               req.Name,
			Intro:              req.Intro,
			Pic:                req.Pic,
			RemotePkOfBrand:    req.RemotePkOfBrand,
			RemotePkOfEmployee: req.RemotePkOfEmpolyee,
		})
		if err != nil {
			return
		}
		slog.Info("2、开通新品牌 ok")
		return
	})
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.Brand = transformBrandEntityToPb(brand)
	return
}

// UpdateBrand 更新品牌
func (s *BrandAPIService) UpdateBrand(ctx context.Context, req *brandGrpc.UpdateBrandRequest) (res *brandGrpc.UpdateBrandResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brandImp->UpdateBrand:%v", req)
	res = &brandGrpc.UpdateBrandResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	arg := sqlc.UpdateBrandParams{
		ID:         req.Id,
		Intro:      sqlc.NSFromString(req.Intro),
		Pic:        sqlc.NSFromString(req.Pic),
		HomepageBg: sqlc.NSFromString(req.HomepageBg),
		Tel:        sqlc.NSFromString(req.Tel),
	}
	brand, err := s.dao.Q.UpdateBrand(ctx, arg)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.Brand = transformBrandEntityToPb(brand)
	return
}

/****************************************************************************************/
/*                               brand entity of query                                  */
/****************************************************************************************/

// GetBrand 获取单个品牌
func (s *BrandAPIService) GetBrand(ctx context.Context, req *brandGrpc.GetBrandRequest) (res *brandGrpc.GetBrandResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brandImp->GetBrand:%v", req)
	res = &brandGrpc.GetBrandResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	brand, err := s.dao.Q.GetBrand(ctx, req.Id)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.Brand = transformBrandEntityToPb(brand)
	return
}

// GetBrandByRemotePK 通过remote_pk获取单个品牌
func (s *BrandAPIService) GetBrandByRemotePK(ctx context.Context, req *brandGrpc.GetBrandByRemotePKRequest) (res *brandGrpc.GetBrandByRemotePKResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brandImp->GetBrandByRemotePK:%v", req)
	res = &brandGrpc.GetBrandByRemotePKResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	brand, sqlErr := s.dao.Q.GetBrandByRemotePK(ctx, req.RemotePk)
	if sqlErr != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    util.Int32IfThenElse(sql.ErrNoRows == sqlErr, 404, 400),
			Msg:     sqlErr.Error(),
		}
		return
	}
	res.Brand = transformBrandEntityToPb(brand)
	return
}

// ListUnmappingedBilinBrands 获取未映射到星团的比邻品牌列表
func (s *BrandAPIService) ListUnmappingedBilinBrands(ctx context.Context, req *brandGrpc.ListUnmappingedBilinBrandsRequest) (res *brandGrpc.ListUnmappingedBilinBrandsResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brandImp->ListUnmappingedBilinBrands:%v", req)
	res = &brandGrpc.ListUnmappingedBilinBrandsResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	userID := req.UserId

	var bilinBrands []model.BilinBrand
	err = s.dao.NewTxRunner().SqlcExecTx(ctx, func(q *sqlc.Queries) (err error) {
		user, err := q.GetUser(ctx, userID)
		if err != nil {
			return
		}
		if !user.Mobile.Valid {
			err = fmt.Errorf("user mobile is invalid")
			return
		}
		userAccountToken, err := s.userService.FetchUserAccountTokenSafely(ctx, q, &user)
		if err != nil {
			return
		}
		slog.Infof("1、获取用户的accountToken ok")

		bilinBrands, err = s.brandService.ListUnmappingedBilinBrands(ctx, q, brandService.ListUnmappingedBilinBrandsParam{
			UserID:           userID,
			UserAccountToken: userAccountToken,
		})
		if err != nil {
			return
		}
		slog.Infof("2、获取未映射到星团的比邻品牌列表 ok")
		return
	})

	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.BilinBrands = mapBilinBrandEntityToPb(bilinBrands, transformBilinBrandEntityToPb)
	return
}

/****************************************************************************************/
/*                            brand_ext entity of helper                                */
/****************************************************************************************/

func transformBrandExtEntityToPb(o sqlc.BrandExt) *brandGrpc.BrandExtEntity {
	return &brandGrpc.BrandExtEntity{
		Id:                   o.ID,
		BrandId:              o.BrandID,
		OwnUserId:            o.OwnUserID,
		WebposToken:          o.WebposToken.String,
		WebposTokenRefreshed: sqlc.GoTimeToPBTimestamp(o.WebposTokenRefreshed),
		IsWxpayAvailable:     o.IsWxpayAvailable,
	}
}

/****************************************************************************************/
/*                            brand_ext entity of cmd                                   */
/****************************************************************************************/

// UpsertBrandExt 插入/更新品牌扩展信息
func (s *BrandAPIService) UpsertBrandExt(ctx context.Context, req *brandGrpc.UpsertBrandExtRequest) (res *brandGrpc.UpsertBrandExtResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brandImp->UpsertBrandExt:%v", req)
	res = &brandGrpc.UpsertBrandExtResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	arg := sqlc.UpsertBrandExtParams{
		BrandID:   req.BrandId,
		OwnUserID: req.OwnUserId,
	}
	brandExt, err := s.dao.Q.UpsertBrandExt(ctx, arg)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.BrandExt = transformBrandExtEntityToPb(brandExt)
	return
}

// RefreshWebposToken 刷新品牌管理的webtoken
func (s *BrandAPIService) RefreshWebposToken(ctx context.Context, req *brandGrpc.RefreshWebposTokenRequest) (res *brandGrpc.RefreshWebposTokenResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brandImp->RefreshWebposToken:%v", req)
	res = &brandGrpc.RefreshWebposTokenResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	arg := sqlc.UpdateBrandExtWebposInfoParams{
		ID:                   req.Id,
		WebposToken:          sqlc.NSFromString(req.WebposToken),
		WebposTokenRefreshed: sqlc.PBTimestampToGoTime(req.WebposTokenRefreshed),
	}
	brandExt, err := s.dao.Q.UpdateBrandExtWebposInfo(ctx, arg)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.BrandExt = transformBrandExtEntityToPb(brandExt)
	return
}

/****************************************************************************************/
/*                            brand_ext entity of query                                 */
/****************************************************************************************/

// GetBrandExtByBrandID  获取单个用户扩展信息
func (s *BrandAPIService) GetBrandExtByBrandID(ctx context.Context, req *brandGrpc.GetBrandExtByBrandIDRequest) (res *brandGrpc.GetBrandExtByBrandIDResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brandImp->GetBrandExtByBrandID:%v", req)
	res = &brandGrpc.GetBrandExtByBrandIDResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	brandExt, err := s.dao.Q.GetBrandExtByBrandID(ctx, req.BrandId)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.BrandExt = transformBrandExtEntityToPb(brandExt)
	return
}

/****************************************************************************************/
/*                            brand_stat entity of helper                               */
/****************************************************************************************/

func transformBrandStatEntityToPb(brandStat sqlc.BrandStat) *brandGrpc.BrandStatEntity {
	return &brandGrpc.BrandStatEntity{
		BrandId:                    brandStat.BrandID,
		FansCount:                  brandStat.FansCount,
		AdminCount:                 brandStat.AdminCount,
		PublishActivityCount:       brandStat.PublishActivityCount,
		SpokesmanCount:             brandStat.SpokesmanCount,
		EndorseRequestToAuditCount: brandStat.EndorseRequestToAuditCount,
	}
}

/****************************************************************************************/
/*                            brand_stat entity of cmd                                  */
/****************************************************************************************/

// UpsertBrandStat 插入/更新品牌统计信息
func (s *BrandAPIService) UpsertBrandStat(ctx context.Context, req *brandGrpc.UpsertBrandStatRequest) (res *brandGrpc.UpsertBrandStatResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brandImp->UpsertBrandStat:%v", req)
	res = &brandGrpc.UpsertBrandStatResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	arg := sqlc.UpsertBrandStatParams{
		BrandID:                    req.BrandId,
		FansCount:                  req.FansCount,
		AdminCount:                 req.AdminCount,
		PublishActivityCount:       req.PublishActivityCount,
		SpokesmanCount:             req.SpokesmanCount,
		EndorseRequestToAuditCount: req.EndorseRequestToAuditCount,
	}
	brandStat, err := s.dao.Q.UpsertBrandStat(ctx, arg)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.BrandStat = transformBrandStatEntityToPb(brandStat)
	return
}

/****************************************************************************************/
/*                            brand_endorsement entity of helper                        */
/****************************************************************************************/

func transformBrandEndorsementEntityToPb(brandEndorsement sqlc.BrandEndorsement) *brandGrpc.BrandEndorsementEntity {
	return &brandGrpc.BrandEndorsementEntity{
		BrandId:              brandEndorsement.BrandID,
		IsOpen:               brandEndorsement.IsOpen,
		SpokesmanTitle:       brandEndorsement.SpokesmanTitle,
		UserStratified:       brandEndorsement.UserStratified,
		ConsumerLowerExpense: brandEndorsement.ConsumerLowerExpense.Int32,
		NeedApplyInfo:        brandEndorsement.NeedApplyInfo,
		ApplyInfoFields:      brandEndorsement.ApplyInfoFields,
		IsEntranceDisplay:    brandEndorsement.IsEntranceDisplay,
		IsAutoApproved:       brandEndorsement.IsAutoApproved,
	}
}

/****************************************************************************************/
/*                            brand_endorsement entity of cmd                           */
/****************************************************************************************/

// UpsertBrandEndorsement 插入/更新品牌代言设置
func (s *BrandAPIService) UpsertBrandEndorsement(ctx context.Context, req *brandGrpc.UpsertBrandEndorsementRequest) (res *brandGrpc.UpsertBrandEndorsementResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brandImp->UpsertBrandEndorsement:%v", req)
	res = &brandGrpc.UpsertBrandEndorsementResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	arg := sqlc.UpsertBrandEndorsementParams{
		BrandID:              req.BrandId,
		IsOpen:               req.IsOpen,
		SpokesmanTitle:       req.SpokesmanTitle,
		UserStratified:       req.UserStratified,
		ConsumerLowerExpense: sqlc.NInt32FromInt32(req.ConsumerLowerExpense),
		NeedApplyInfo:        req.NeedApplyInfo,
		ApplyInfoFields:      req.ApplyInfoFields,
		IsEntranceDisplay:    req.IsEntranceDisplay,
		IsAutoApproved:       req.IsAutoApproved,
	}
	brandEndorsement, err := s.dao.Q.UpsertBrandEndorsement(ctx, arg)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.BrandEndorsement = transformBrandEndorsementEntityToPb(brandEndorsement)
	return
}

/****************************************************************************************/
/*                            brand_endorsement entity of query                         */
/****************************************************************************************/

// GetBrandEndorsementByBrandID  获取单个品牌代言信息
func (s *BrandAPIService) GetBrandEndorsementByBrandID(ctx context.Context, req *brandGrpc.GetBrandEndorsementByBrandIDRequest) (res *brandGrpc.GetBrandEndorsementByBrandIDResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brandImp->GetBrandEndorsementByBrandID:%v", req)
	res = &brandGrpc.GetBrandEndorsementByBrandIDResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	brandEndorsement, sqlErr := s.dao.Q.GetBrandEndorsementByBrandID(ctx, req.BrandId)
	if sqlErr != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    util.Int32IfThenElse(sql.ErrNoRows == sqlErr, 404, 400),
			Msg:     sqlErr.Error(),
		}
		return
	}
	res.BrandEndorsement = transformBrandEndorsementEntityToPb(brandEndorsement)
	return
}

/****************************************************************************************/
/*                            brand_distribute_endorsement entity of helper             */
/****************************************************************************************/

func transformBrandDistributeEndorsementEntityToPb(o sqlc.BrandDistributeEndorsement) *brandGrpc.BrandDistributeEndorsementEntity {
	return &brandGrpc.BrandDistributeEndorsementEntity{
		BrandId:              o.BrandID,
		IsOpen:               o.IsOpen,
		DistributorTitle:     o.DistributorTitle,
		UserStratified:       o.UserStratified,
		ConsumerLowerExpense: o.ConsumerLowerExpense.Int32,
		NeedApplyInfo:        o.NeedApplyInfo,
		ApplyInfoFields:      o.ApplyInfoFields,
		IsEntranceDisplay:    o.IsEntranceDisplay,
		IsAutoApproved:       o.IsAutoApproved,
	}
}

/****************************************************************************************/
/*                            brand_distribute_endorsement entity of cmd                */
/****************************************************************************************/

// UpsertBrandDistributeEndorsement 插入/更新品牌分销招募设置
func (s *BrandAPIService) UpsertBrandDistributeEndorsement(ctx context.Context, req *brandGrpc.UpsertBrandDistributeEndorsementRequest) (res *brandGrpc.UpsertBrandDistributeEndorsementResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brandImp->UpsertBrandDistributeEndorsement:%v", req)
	res = &brandGrpc.UpsertBrandDistributeEndorsementResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	q := s.dao.Q

	brandDistributeEndorsement, err := q.UpsertBrandDistributeEndorsement(ctx, sqlc.UpsertBrandDistributeEndorsementParams{
		BrandID:              req.BrandId,
		IsOpen:               req.IsOpen,
		DistributorTitle:     req.DistributorTitle,
		UserStratified:       req.UserStratified,
		ConsumerLowerExpense: sqlc.NInt32FromInt32(req.ConsumerLowerExpense),
		NeedApplyInfo:        req.NeedApplyInfo,
		ApplyInfoFields:      req.ApplyInfoFields,
		IsEntranceDisplay:    req.IsEntranceDisplay,
		IsAutoApproved:       req.IsAutoApproved,
	})
	if err != nil {
		return
	}
	res.BrandDistributeEndorsement = transformBrandDistributeEndorsementEntityToPb(brandDistributeEndorsement)
	return
}

/****************************************************************************************/
/*                            brand_distribute_endorsement entity of query              */
/****************************************************************************************/

// GetBrandDistributeEndorsementByBrandID  获取单个品牌分销招募信息
func (s *BrandAPIService) GetBrandDistributeEndorsementByBrandID(ctx context.Context, req *brandGrpc.GetBrandDistributeEndorsementByBrandIDRequest) (res *brandGrpc.GetBrandDistributeEndorsementByBrandIDResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brandImp->GetBrandDistributeEndorsementByBrandID:%v", req)
	res = &brandGrpc.GetBrandDistributeEndorsementByBrandIDResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	brandDistributeEndorsement, sqlErr := s.dao.Q.GetBrandDistributeEndorsementByBrandID(ctx, req.BrandId)
	if sqlErr != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    util.Int32IfThenElse(sql.ErrNoRows == sqlErr, 404, 400),
			Msg:     sqlErr.Error(),
		}
		return
	}
	res.BrandDistributeEndorsement = transformBrandDistributeEndorsementEntityToPb(brandDistributeEndorsement)
	return
}

/****************************************************************************************/
/*                            brand_distribute_supply_setting entity of helper          */
/****************************************************************************************/
func transformBrandDistributeSupplySettingEntityToPb(warehouseIds []int64) func(sqlc.BrandDistributeSupplySetting) *brandGrpc.BrandDistributeSupplySettingEntity {
	return func(o sqlc.BrandDistributeSupplySetting) *brandGrpc.BrandDistributeSupplySettingEntity {
		return &brandGrpc.BrandDistributeSupplySettingEntity{
			BrandId:                       o.BrandID,
			DeliveryModes:                 o.DeliveryModes,
			IsUseWarehouseShippingFeeRule: o.IsUseWarehouseShippingFeeRule,
			UnifiedShippingFee:            o.UnifiedShippingFee.Int32,
			WarehouseIds:                  warehouseIds,
		}
	}
}

/****************************************************************************************/
/*                            brand_distribute_supply_setting entity of cmd             */
/****************************************************************************************/

// UpsertBrandDistributeSupplySetting 插入/更新品牌分销供货设置
func (s *BrandAPIService) UpsertBrandDistributeSupplySetting(ctx context.Context, req *brandGrpc.UpsertBrandDistributeSupplySettingRequest) (res *brandGrpc.UpsertBrandDistributeSupplySettingResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brandImp->UpsertBrandDistributeSupplySetting:%v", req)
	res = &brandGrpc.UpsertBrandDistributeSupplySettingResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	brandID := req.BrandId
	warehouseIDs := req.WarehouseIds

	if len(warehouseIDs) == 0 {
		err = fmt.Errorf("没有设置供货仓库")
		return
	}
	var brandDistributeSupplySetting sqlc.BrandDistributeSupplySetting
	err = s.dao.NewTxRunner().SqlcExecTx(ctx, func(q *sqlc.Queries) (err error) {
		brandDistributeSupplySetting, err = q.UpsertBrandDistributeSupplySetting(ctx, sqlc.UpsertBrandDistributeSupplySettingParams{
			BrandID:                       brandID,
			DeliveryModes:                 req.DeliveryModes,
			IsUseWarehouseShippingFeeRule: req.IsUseWarehouseShippingFeeRule,
			UnifiedShippingFee:            sqlc.NInt32FromInt32(req.UnifiedShippingFee),
		})
		if err != nil {
			return
		}

		err = s.brandService.RefreshBrandDistributeWarehousesByBrandID(ctx, q, brandID, warehouseIDs)
		if err != nil {
			return
		}
		return
	})
	if err != nil {
		return
	}
	res.BrandDistributeSupplySetting = transformBrandDistributeSupplySettingEntityToPb(warehouseIDs)(brandDistributeSupplySetting)
	return
}

/****************************************************************************************/
/*                            brand_distribute_supply_setting entity of query           */
/****************************************************************************************/

// GetBrandDistributeSupplySettingByBrandID  获取单个品牌分销供货设置
func (s *BrandAPIService) GetBrandDistributeSupplySettingByBrandID(ctx context.Context, req *brandGrpc.GetBrandDistributeSupplySettingByBrandIDRequest) (res *brandGrpc.GetBrandDistributeSupplySettingByBrandIDResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brandImp->GetBrandDistributeSupplySettingByBrandID:%v", req)
	res = &brandGrpc.GetBrandDistributeSupplySettingByBrandIDResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	q := s.dao.Q
	brandID := req.BrandId

	brandDistributeSupplySetting, sqlErr := q.GetBrandDistributeSupplySettingByBrandID(ctx, brandID)
	if sqlErr != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    util.Int32IfThenElse(sql.ErrNoRows == sqlErr, 404, 400),
			Msg:     sqlErr.Error(),
		}
		return
	}
	brandDistributeWarehousePtrs, err := s.brandService.ListBrandDistributeWarehousePtrsByBrandID(ctx, q, brandID)
	if err != nil {
		return
	}
	warehouseIDs := s.brandService.MapBrandDistributeWarehousePtrsToWarehouseIDs(brandDistributeWarehousePtrs)
	res.BrandDistributeSupplySetting = transformBrandDistributeSupplySettingEntityToPb(warehouseIDs)(brandDistributeSupplySetting)
	return
}

/****************************************************************************************/
/*                            brand_distribute_product entity of helper                 */
/****************************************************************************************/
func (s *BrandAPIService) transformBrandDistributeProductEntityToProductWithDistributeInfoPb(productPtr *sqlc.Product) func(*sqlc.BrandDistributeProduct) *message.ProductWithDistributeInfo {
	return func(ptr *sqlc.BrandDistributeProduct) *message.ProductWithDistributeInfo {
		return &message.ProductWithDistributeInfo{
			ProductId:      productPtr.ID,
			Name:           productPtr.Name,
			Pics:           productPtr.Pics,
			HasSpecs:       productPtr.HasSpecs,
			PriceMin:       productPtr.PriceMin,
			PriceMax:       productPtr.PriceMax,
			ProductGroupId: productPtr.ProductGroupID.Int64,
			PercentSale:    ptr.PercentSale,
			PercentOff:     ptr.PercentOff,
		}
	}
}

// func (s *BrandAPIService) transformListNormalProductWithDistributeInfosByBrandIDRowToProductWithDistributeInfoPb() func(*sqlc.ListNormalProductWithDistributeInfosByBrandIDRow) *message.ProductWithDistributeInfo {
// 	return func(ptr *sqlc.ListNormalProductWithDistributeInfosByBrandIDRow) *message.ProductWithDistributeInfo {
// 		return &message.ProductWithDistributeInfo{
// 			ProductId:      ptr.ID,
// 			Name:           ptr.Name,
// 			Pics:           ptr.Pics,
// 			HasSpecs:       ptr.HasSpecs,
// 			PriceMin:       ptr.PriceMin,
// 			PriceMax:       ptr.PriceMax,
// 			ProductGroupId: ptr.ProductGroupID.Int64,
// 			PercentSale:    ptr.PercentSale,
// 			PercentOff:     ptr.PercentOff,
// 		}
// 	}
// }

// func mapListNormalProductWithDistributeInfosByBrandIDRowToProductWithDistributeInfoPb(list []*sqlc.ListNormalProductWithDistributeInfosByBrandIDRow, f func(*sqlc.ListNormalProductWithDistributeInfosByBrandIDRow) *message.ProductWithDistributeInfo) []*message.ProductWithDistributeInfo {
// 	r := make([]*message.ProductWithDistributeInfo, len(list))
// 	for i, item := range list {
// 		r[i] = f(item)
// 	}
// 	return r
// }

/****************************************************************************************/
/*                            brand_distribute_product entity of cmd                    */
/****************************************************************************************/

// UpsertBrandDistributeProduct 插入/更新品牌分销供货商品
func (s *BrandAPIService) UpsertBrandDistributeProduct(ctx context.Context, req *brandGrpc.UpsertBrandDistributeProductRequest) (res *brandGrpc.UpsertBrandDistributeProductResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brandImp->UpsertBrandDistributeProduct:%v", req)
	res = &brandGrpc.UpsertBrandDistributeProductResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	q := s.dao.Q
	brandID := req.BrandId
	productID := req.ProductId
	percentSale := req.PercentSale
	percentOff := req.PercentOff
	if percentSale < 0 {
		err = fmt.Errorf("销售比例无效")
		return
	}
	if percentOff < 0 || percentOff > 1000 {
		err = fmt.Errorf("供货比例无效")
		return
	}

	brandDistributeSupplySettingPtr, err := s.brandService.UpsertBrandDistributeProduct(ctx, q, &brandService.UpsertBrandDistributeProductParam{
		BrandID:     brandID,
		ProductID:   productID,
		PercentSale: percentSale,
		PercentOff:  percentOff,
	})
	if err != nil {
		return
	}
	productPtr, err := s.productService.GetProductPtr(ctx, q, productID)
	if err != nil {
		return
	}
	res.ProductWithDistributeInfo = s.transformBrandDistributeProductEntityToProductWithDistributeInfoPb(productPtr)(brandDistributeSupplySettingPtr)
	return
}

// BatchUpsertBrandDistributeProducts 批量插入/更新品牌分销供货商品
func (s *BrandAPIService) BatchUpsertBrandDistributeProducts(ctx context.Context, req *brandGrpc.BatchUpsertBrandDistributeProductsRequest) (res *brandGrpc.BatchUpsertBrandDistributeProductsResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brandImp->BatchUpsertBrandDistributeProducts:%v", req)
	res = &brandGrpc.BatchUpsertBrandDistributeProductsResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	q := s.dao.Q
	brandID := req.BrandId
	percentSale := req.PercentSale
	percentOff := req.PercentOff
	if percentSale < 0 {
		err = fmt.Errorf("销售比例无效")
		return
	}
	if percentOff < 0 || percentOff > 1000 {
		err = fmt.Errorf("供货比例无效")
		return
	}

	err = s.brandService.BatchUpsertBrandDistributeProducts(ctx, q, &brandService.UpsertBrandDistributeProductParam{
		BrandID:     brandID,
		PercentSale: percentSale,
		PercentOff:  percentOff,
	})
	if err != nil {
		return
	}
	return
}

/****************************************************************************************/
/*                            brand_distribute_product entity of query                  */
/****************************************************************************************/

// ListBrandProductWithDistributeInfos  列出品牌供货商品
func (s *BrandAPIService) ListBrandProductWithDistributeInfos(ctx context.Context, req *brandGrpc.ListBrandProductWithDistributeInfosRequest) (res *brandGrpc.ListBrandProductWithDistributeInfosResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brandImp->ListBrandProductWithDistributeInfos:%v", req)
	res = &brandGrpc.ListBrandProductWithDistributeInfosResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	q := s.dao.Q
	ts := sqlc.PBTimestampToGoTime(req.Ts)
	brandID := req.BrandId
	productGroupID := req.ProductGroupId
	keyword := req.Keyword

	total, ptrs, err := s.productService.ListNormalProductWithDistributeInfoPtrsOfBrand(ctx, q, brandID,
		&util.Pager{
			Ts:     ts,
			Limit:  req.Limit,
			Offset: req.Offset,
		}, &productService.ListNormalProductWithDistributeInfoPtrsParam{

			ProductGroupID: productGroupID,
			Keyword:        keyword,
		})
	if err != nil {
		return
	}

	// 品牌接口不用带属性组值和规格
	var productAttributeKeys []sqlc.ProductAttributeKey
	var productAttributeValues []sqlc.ProductAttributeValue
	var productSpecs []sqlc.ProductSpec

	// productIDs := util.MapToInt64(util.ToGenericSlice(ptrs), func(v interface{}) int64 {
	// 	val := v.(*sqlc.ListNormalProductWithDistributeInfosByBrandIDRow)
	// 	return val.ID
	// })

	// productAttributeKeys, err := s.dao.Q.ListNormalProductAttributeKeysByProductIDs(ctx, productIDs)
	// if err != nil {
	// 	return
	// }

	// productAttributeValues, err := s.dao.Q.ListNormalProductAttributeValuesByProductIDs(ctx, productIDs)
	// if err != nil {
	// 	return
	// }

	// productSpecs, err := s.dao.Q.ListNormalProductSpecsByProductIDs(ctx, productIDs)
	// if err != nil {
	// 	return
	// }

	res.Total = total
	res.ProductWithDistributeInfos = shared.MapListNormalProductWithDistributeInfosByBrandIDRowToProductWithDistributeInfoPb(ptrs,
		shared.TransformListNormalProductWithDistributeInfosByBrandIDRowToProductWithDistributeInfoPb(productAttributeKeys, productAttributeValues, productSpecs))
	return
}

/****************************************************************************************/
/*                            brandJoins entity of helper                               */
/****************************************************************************************/

func transformGetBrandWithExtAndStatRowEntityToPb(row sqlc.GetBrandWithExtAndStatRow) *brandGrpc.BrandWithExtAndStatEntity {
	return &brandGrpc.BrandWithExtAndStatEntity{
		// brand
		Id:         row.ID,
		Origin:     row.Origin,
		Name:       row.Name,
		Intro:      row.Intro.String,
		Pic:        row.Pic.String,
		HomepageBg: row.HomepageBg.String,
		Tel:        row.Tel.String,
		Opened:     sqlc.GoTimeToPBTimestamp(row.Opened),

		// brand_ext
		OwnUserId:           row.OwnUserID,
		IsWxpayAvailable:    row.IsWxpayAvailable,
		IsDuringApplication: row.IsDuringApplication,

		// brand_stat
		FansCount:                  row.FansCount,
		AdminCount:                 row.AdminCount,
		PublishActivityCount:       row.PublishActivityCount,
		SpokesmanCount:             row.SpokesmanCount,
		EndorseRequestToAuditCount: row.EndorseRequestToAuditCount,
	}
}

func transformGetBrandWithExtAndStatAndEndorsementForUserRowEntityToPb(row sqlc.GetBrandWithExtAndStatAndEndorsementForUserRow) *brandGrpc.BrandWithExtAndStatAndEndorsementEntity {
	return &brandGrpc.BrandWithExtAndStatAndEndorsementEntity{
		// brand
		Id:         row.ID,
		Origin:     row.Origin,
		Name:       row.Name,
		Intro:      row.Intro.String,
		Pic:        row.Pic.String,
		HomepageBg: row.HomepageBg.String,
		Tel:        row.Tel.String,
		Opened:     sqlc.GoTimeToPBTimestamp(row.Opened),

		// brand_ext
		OwnUserId:           row.OwnUserID,
		IsWxpayAvailable:    row.IsWxpayAvailable,
		IsDuringApplication: row.IsDuringApplication,

		// brand_stat
		FansCount:                  row.FansCount,
		AdminCount:                 row.AdminCount,
		PublishActivityCount:       row.PublishActivityCount,
		SpokesmanCount:             row.SpokesmanCount,
		EndorseRequestToAuditCount: row.EndorseRequestToAuditCount,

		// distribute
		IsDistributionEntranceDisplay: row.IsDistributionEntranceDisplay,
		DistributorId:                 row.DistributorID,

		// endorsement
		IsEndorsementEntranceDisplay: row.IsEndorsementEntranceDisplay,
		EndorseSpokesmanId:           row.EndorseSpokesmanID,
	}
}

func transformListBrandWithStatByUserIDAsAdminRowEntityToPb(row sqlc.ListBrandWithStatsByUserIDAsAdminRow) *brandGrpc.BrandWithStatEntity {
	return &brandGrpc.BrandWithStatEntity{
		// brand
		Id:         row.ID,
		Origin:     row.Origin,
		Name:       row.Name,
		Intro:      row.Intro.String,
		Pic:        row.Pic.String,
		HomepageBg: row.HomepageBg.String,
		Tel:        row.Tel.String,
		Opened:     sqlc.GoTimeToPBTimestamp(row.Opened),
		// brand_stat
		FansCount:                  row.FansCount,
		AdminCount:                 row.AdminCount,
		PublishActivityCount:       row.PublishActivityCount,
		SpokesmanCount:             row.SpokesmanCount,
		EndorseRequestToAuditCount: row.EndorseRequestToAuditCount,
	}
}

func mapBrandWithStatByUserIDAsAdminEntityToPb(list []sqlc.ListBrandWithStatsByUserIDAsAdminRow, f func(sqlc.ListBrandWithStatsByUserIDAsAdminRow) *brandGrpc.BrandWithStatEntity) []*brandGrpc.BrandWithStatEntity {
	r := make([]*brandGrpc.BrandWithStatEntity, len(list))
	for i, item := range list {
		r[i] = f(item)
	}
	return r
}

func transformActivityTypeAsFeatureAvailableEntityToPb(o *model.ActivityTypeAsFeatureCheckAvailable) *brandGrpc.ActivityTypeAsFeatureAvailableEntity {
	return &brandGrpc.ActivityTypeAsFeatureAvailableEntity{
		ActivityType: o.ActivityType,
		IsAvailable:  o.IsAvailable,
	}
}

func mapActivityTypeAsFeatureAvailableEntityToPb(list []*model.ActivityTypeAsFeatureCheckAvailable, f func(*model.ActivityTypeAsFeatureCheckAvailable) *brandGrpc.ActivityTypeAsFeatureAvailableEntity) []*brandGrpc.ActivityTypeAsFeatureAvailableEntity {
	r := make([]*brandGrpc.ActivityTypeAsFeatureAvailableEntity, len(list))
	for i, item := range list {
		r[i] = f(item)
	}
	return r
}

/****************************************************************************************/
/*                            brandJoins entity of query                                */
/****************************************************************************************/

// GetBrandWithExtAndStat  获取单个品牌信息+品牌扩展信息+品牌统计信息
func (s *BrandAPIService) GetBrandWithExtAndStat(ctx context.Context, req *brandGrpc.GetBrandWithExtAndStatRequest) (res *brandGrpc.GetBrandWithExtAndStatResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brandImp->GetBrandWithExtAndStat:%v", req)
	res = &brandGrpc.GetBrandWithExtAndStatResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	brandWithExtAndStat, err := s.dao.Q.GetBrandWithExtAndStat(ctx, req.Id)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.BrandWithExtAndStat = transformGetBrandWithExtAndStatRowEntityToPb(brandWithExtAndStat)
	return
}

// GetBrandWithExtAndStat  获取单个品牌信息+品牌扩展信息+品牌统计信息
func (s *BrandAPIService) GetBrandWithExtAndStatAndEndorsementForUser(ctx context.Context, req *brandGrpc.GetBrandWithExtAndStatAndEndorsementForUserRequest) (res *brandGrpc.GetBrandWithExtAndStatAndEndorsementForUserResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brandImp->GetBrandWithExtAndStatAndEndorsementForUser:%v", req)
	res = &brandGrpc.GetBrandWithExtAndStatAndEndorsementForUserResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}

	q := s.dao.Q
	brandID := req.Id
	userID := req.UserId

	brandWithExtAndStatAndEndorsement, err := q.GetBrandWithExtAndStatAndEndorsementForUser(ctx, sqlc.GetBrandWithExtAndStatAndEndorsementForUserParams{
		ID:     brandID,
		UserID: userID,
	})
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	// check available of activity as features
	checkResults, err := s.activityService.CheckAvailableActivityAsFeatureForBrand(ctx, q, brandID)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}

	res.BrandWithExtAndStatAndEndorsement = transformGetBrandWithExtAndStatAndEndorsementForUserRowEntityToPb(brandWithExtAndStatAndEndorsement)
	res.ActivityAsFeatureAvailables = mapActivityTypeAsFeatureAvailableEntityToPb(checkResults, transformActivityTypeAsFeatureAvailableEntityToPb)
	return
}

// ListBrandWithStatsByUserIDAsAdmin  作为管理员获取品牌信息+品牌统计信息列表
func (s *BrandAPIService) ListBrandWithStatsByUserIDAsAdmin(ctx context.Context, req *brandGrpc.ListBrandWithStatsByUserIDAsAdminRequest) (res *brandGrpc.ListBrandWithStatsByUserIDAsAdminResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brandImp->ListBrandWithStatsByUserIDAsAdmin:%v", req)
	res = &brandGrpc.ListBrandWithStatsByUserIDAsAdminResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	total, err := s.dao.Q.CountBrandWithStatsByUserIDAsAdmin(ctx, req.UserId)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}

	if total == 0 {
		// 不用继续调用listfunc
		return
	}

	arg := sqlc.ListBrandWithStatsByUserIDAsAdminParams{
		Limit:  req.Limit,
		Offset: req.Offset,
		UserID: req.UserId,
	}
	brandWithStats, err := s.dao.Q.ListBrandWithStatsByUserIDAsAdmin(ctx, arg)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.Total = total
	res.BrandWithStats = mapBrandWithStatByUserIDAsAdminEntityToPb(brandWithStats, transformListBrandWithStatByUserIDAsAdminRowEntityToPb)
	return
}

/****************************************************************************************/
/*                            brand account of helper                                   */
/****************************************************************************************/

func transformBrandSettlementAccountInfoEntityToPb(brandID int64, o *model.BrandSettlementAccountInfo) *brandGrpc.BrandSettlementAccountInfoEntity {
	return &brandGrpc.BrandSettlementAccountInfoEntity{
		BrandId:             brandID,
		AvailableAmount:     o.AvailableAmount,
		PendingAmount:       o.PendingAmount,
		WithdrawingAmount:   o.WithdrawingAmount,
		WithdrawedAmount:    o.WithdrawedAmount,
		AccountBank:         o.AccountBank,
		AccountNumberSuffix: o.AccountNumberSuffix,
	}
}

func transformBrandAccountWithdrawApplymentEntityToPb(o sqlc.BrandAccountWithdrawApplyment) *brandGrpc.BrandAccountWithdrawApplymentEntity {
	return &brandGrpc.BrandAccountWithdrawApplymentEntity{
		Id:         o.ID,
		BrandId:    o.BrandID,
		UserId:     o.UserID,
		Applied:    sqlc.GoTimeToPBTimestamp(o.Applied),
		Amount:     o.Amount,
		Remark:     o.Remark.String,
		ApplyState: o.ApplyState,
	}
}

func mapBrandAccountWithdrawApplymentEntityToPb(list []sqlc.BrandAccountWithdrawApplyment, f func(sqlc.BrandAccountWithdrawApplyment) *brandGrpc.BrandAccountWithdrawApplymentEntity) []*brandGrpc.BrandAccountWithdrawApplymentEntity {
	r := make([]*brandGrpc.BrandAccountWithdrawApplymentEntity, len(list))
	for i, item := range list {
		r[i] = f(item)
	}
	return r
}

/****************************************************************************************/
/*                            brand account of cmd                                      */
/****************************************************************************************/

// CreateBrandAccountWithdrawApplyment 创建提现申请
func (s *BrandAPIService) CreateBrandAccountWithdrawApplyment(ctx context.Context, req *brandGrpc.CreateBrandAccountWithdrawApplymentRequest) (res *brandGrpc.CreateBrandAccountWithdrawApplymentResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brandImp->CreateBrandAccountWithdrawApplyment:%v", req)
	res = &brandGrpc.CreateBrandAccountWithdrawApplymentResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}

	var brandAccountWithdrawApplyment sqlc.BrandAccountWithdrawApplyment
	err = s.dao.NewTxRunner().SqlcExecTx(ctx, func(q *sqlc.Queries) (err error) {

		brandAccountWithdrawApplyment, err = s.brandService.SubmitAccountWithdrawApplyment(ctx, q, brandService.SubmitAccountWithdrawApplymentParam{
			BrandID:  req.BrandId,
			UserID:   req.UserId,
			Amount:   req.Amount,
			Remark:   req.Remark,
			BankMemo: "",
		})

		if err != nil {
			return err
		}

		return
	})

	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.BrandAccountWithdrawApplyment = transformBrandAccountWithdrawApplymentEntityToPb(brandAccountWithdrawApplyment)
	return
}

// ListBrandAccountWithdrawApplyments 分页获取多条提现记录
func (s *BrandAPIService) ListBrandAccountWithdrawApplyments(ctx context.Context, req *brandGrpc.ListBrandAccountWithdrawApplymentsRequest) (res *brandGrpc.ListBrandAccountWithdrawApplymentsResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brandImp->ListBrandAccountWithdrawApplyments:%v", req)

	res = &brandGrpc.ListBrandAccountWithdrawApplymentsResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	q := s.dao.Q
	brandID := req.BrandId

	total, err := q.CountBrandAccountWithdrawApplymentsByBrandID(ctx, brandID)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}

	if total == 0 {
		// 不用继续调用listfunc
		return
	}

	brandAccountWithdrawApplyments, err := q.ListBrandAccountWithdrawApplymentsByBrandID(ctx, sqlc.ListBrandAccountWithdrawApplymentsByBrandIDParams{
		Limit:   req.Limit,
		Offset:  req.Offset,
		BrandID: brandID,
	})
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.Total = total
	res.BrandAccountWithdrawApplyments = mapBrandAccountWithdrawApplymentEntityToPb(brandAccountWithdrawApplyments, transformBrandAccountWithdrawApplymentEntityToPb)
	return
}

/****************************************************************************************/
/*                            brand account of query                                    */
/****************************************************************************************/

// GetSettlementAccountInfo  获取品牌结算账户信息
func (s *BrandAPIService) GetSettlementAccountInfo(ctx context.Context, req *brandGrpc.GetSettlementAccountInfoRequest) (res *brandGrpc.GetSettlementAccountInfoResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brandImp->GetSettlementAccountInfo:%v", req)
	res = &brandGrpc.GetSettlementAccountInfoResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	q := s.dao.Q
	brandID := req.BrandId
	brandSettlementAccountInfoPtr, err := s.brandService.GetSettlementAccountInfo(ctx, q, brandID)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}

	res.BrandSettlementAccountInfo = transformBrandSettlementAccountInfoEntityToPb(brandID, brandSettlementAccountInfoPtr)
	return
}

/****************************************************************************************/
/*                            brand_account_log entity of helper                        */
/****************************************************************************************/

func transformBrandAccountLogEntityToPb(o sqlc.BrandAccountLog) *message.AccountLogInfo {
	return &message.AccountLogInfo{
		Id:       o.ID,
		Logged:   sqlc.GoTimeToPBTimestamp(o.Logged),
		Category: o.Category,
		Amount:   o.Amount,
		Subject:  o.Subject,
		ExtInfo:  o.ExtInfo,
	}
}

func mapBrandAccountLogEntityToPb(list []sqlc.BrandAccountLog, f func(sqlc.BrandAccountLog) *message.AccountLogInfo) []*message.AccountLogInfo {
	r := make([]*message.AccountLogInfo, len(list))
	for i, item := range list {
		r[i] = f(item)
	}
	return r
}

/****************************************************************************************/
/*                            brand_account_log of query                                */
/****************************************************************************************/

// ListBrandAccountLogs  获取品牌资金明细
func (s *BrandAPIService) ListBrandAccountLogs(ctx context.Context, req *brandGrpc.ListBrandAccountLogsRequest) (res *brandGrpc.ListBrandAccountLogsResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brandImp->ListBrandAccountLogs:%v", req)
	res = &brandGrpc.ListBrandAccountLogsResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	q := s.dao.Q
	total, err := q.CountBrandAccountLogsByBrandID(ctx, req.BrandId)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}

	if total == 0 {
		// 不用继续调用listfunc
		return
	}

	arg := sqlc.ListBrandAccountLogsByBrandIDParams{
		Limit:   req.Limit,
		Offset:  req.Offset,
		BrandID: req.BrandId,
	}
	brandAccountLogs, err := q.ListBrandAccountLogsByBrandID(ctx, arg)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	s.slog.Info("========>>>>>>")
	res.Total = total
	res.AccountLogs = mapBrandAccountLogEntityToPb(brandAccountLogs, transformBrandAccountLogEntityToPb)
	return
}

// AggrBrandAccountLogsToInOut 统计品牌资金的收入与支出
func (s *BrandAPIService) AggrBrandAccountLogsToInOut(ctx context.Context, req *brandGrpc.AggrBrandAccountLogsToInOutRequest) (res *brandGrpc.AggrBrandAccountLogsToInOutResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brandImp->AggrBrandAccountLogsToInOut:%v", req)

	res = &brandGrpc.AggrBrandAccountLogsToInOutResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	q := s.dao.Q

	aggrRet, err := q.AggrBrandAccountLogsToInOut(ctx, sqlc.AggrBrandAccountLogsToInOutParams{
		Logged:   sqlc.PBTimestampToGoTime(req.Begin),
		Logged_2: sqlc.PBTimestampToGoTime(req.End),
		BrandID:  req.BrandId,
	})
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.Income = aggrRet.Income
	res.Outlay = aggrRet.Outlay
	return
}
